<template>
  <div class="" ref="body">
    <canvas class="box" id="canvas" width="600" height="600"></canvas>
    <div class="signBox">
      <div>现在是轮到{{this.redOrblack? '灰色': '红色'}}</div>
      <div :class="['piece', this.redOrblack? 'ccc': 'red']"></div>
      <div class="backOne" id="backOne">悔棋</div>
      <div class="beforeBackOne" id="beforeBackOne">撤销悔棋</div>
    </div>
  </div>
</template>
<script>
var _mine
export default {
  data () {
    return {
      isWinner: false,
      piece: [],
      redOrblack: true,
      // 已经放下的棋子
      downSpot: [],
      // 悔棋
      regret: [],
      // 红色棋子的信息
      redSpot: [],
      // 黑色棋子的信息
      blackSpot: [],
      num: 0,
      // 判定胜负用的规则
      rule1: { x: 0, y: 40 },
      rule2: { x: 40, y: 0 },
      rule3: { x: 40, y: 40 },
      rule4: { x: 0, y: -40 },
      rule5: { x: -40, y: 0 },
      rule6: { x: -40, y: -40 },
      rule7: { x: -40, y: 40 },
      rule8: { x: 40, y: -40 }
    }
  },
  methods: {
    // 判定胜负
    winner (spot, spotArr) {
      let num = 0
      num = num + 0
      // 定义8个方向，根据传入的棋子和数组去查询是否满足胜利条件
      this.checkRule1(spot, spotArr, _mine.checkRule1, num)
      this.checkRule2(spot, spotArr, _mine.checkRule2, num)
      this.checkRule3(spot, spotArr, _mine.checkRule3, num)
      this.checkRule4(spot, spotArr, _mine.checkRule4, num)
      this.checkRule5(spot, spotArr, _mine.checkRule5, num)
      this.checkRule6(spot, spotArr, _mine.checkRule6, num)
      this.checkRule7(spot, spotArr, _mine.checkRule7, num)
      this.checkRule8(spot, spotArr, _mine.checkRule8, num)
    },
    // 判定方法
    checked (spotID, arr, fn, num, spot) {
      console.log(arr)
      for (let i = 0; i < arr.length; i++) {
        // eslint-disable-next-line eqeqeq
        if (spotID == arr[i].sign) {
          num++
          console.log(num)
          if (num >= 4) {
            alert((_mine.redOrblack ? '红色' : '灰色') + 'win! 点击重置即可进行下一局')
            this.isWinner = true
            return
          }
          fn(arr[i], arr, fn, num)
        }
      }
    },
    // 横线
    xLine (ctx, size) {
      ctx.beginPath()
      ctx.moveTo(20, 20 + size)
      ctx.lineTo(580, 20 + size)
      ctx.stroke()
    },
    // 竖线
    yLine (ctx, size) {
      ctx.beginPath()
      ctx.moveTo(20 + size, 20)
      ctx.lineTo(20 + size, 580)
      ctx.stroke()
    },
    // 绘制棋盘
    drawCheckerBoard (ctx, grid, lineTotal) {
      for (let i = 0; i < lineTotal; i++) {
        this.xLine(ctx, grid * i)
        this.yLine(ctx, grid * i)
      }
    },
    // 每个点都预先绘制一个棋子
    drawPiece (ctx, grid, lineTotal) {
      // for循环嵌套绘制整个棋盘的棋子
      for (let i = 0; i < lineTotal; i++) {
        // 绘制行
        for (let s = 0; s < lineTotal; s++) {
          // 存储每个棋子的位置
          const obj = {
            x: 20 + i * grid,
            y: 20 + s * grid,
            r: 10,
            size: {
              min: [10 + i * grid, 10 + s * grid],
              max: [30 + i * grid, 30 + s * grid]
            },
            sign: (20 + i * grid) + '' + (20 + s * grid)
          }
          this.piece.push(obj)
          // 绘制列
          ctx.beginPath()
          ctx.arc(20 + i * grid, 20 + s * grid, 10, 0, Math.PI * 2)
        }
      }
    },
    getMousePos (canvas, e) {
      var rect = canvas.getBoundingClientRect()
      return {
        x: e.clientX - rect.left * (canvas.width / rect.width),
        y: e.clientY - rect.top * (canvas.height / rect.height)
      }
    },
    // 八个方向的判定规则
    checkRule1 (spot, spotArr, fn, num) {
      const x = spot.x + _mine.rule1.x + ''
      const y = spot.y + _mine.rule1.y + ''
      const ID = x + y
      _mine.checked(ID, spotArr, fn, num, spot)
    },
    checkRule2 (spot, spotArr, fn, num) {
      const x = spot.x + _mine.rule2.x + ''
      const y = spot.y + _mine.rule2.y + ''
      const ID = x + y
      _mine.checked(ID, spotArr, fn, num, spot)
    },
    checkRule3 (spot, spotArr, fn, num) {
      const x = spot.x + _mine.rule3.x + ''
      const y = spot.y + _mine.rule3.y + ''
      const ID = x + y
      _mine.checked(ID, spotArr, fn, num, spot)
    },
    checkRule4 (spot, spotArr, fn, num) {
      const x = spot.x + _mine.rule4.x + ''
      const y = spot.y + _mine.rule4.y + ''
      const ID = x + y
      _mine.checked(ID, spotArr, fn, num, spot)
    },
    checkRule5 (spot, spotArr, fn, num) {
      const x = spot.x + _mine.rule5.x + ''
      const y = spot.y + _mine.rule5.y + ''
      const ID = x + y
      _mine.checked(ID, spotArr, fn, num, spot)
    },
    checkRule6 (spot, spotArr, fn, num) {
      const x = spot.x + _mine.rule6.x + ''
      const y = spot.y + _mine.rule6.y + ''
      const ID = x + y
      _mine.checked(ID, spotArr, fn, num, spot)
    },
    checkRule7 (spot, spotArr, fn, num) {
      const x = spot.x + _mine.rule7.x + ''
      const y = spot.y + _mine.rule7.y + ''
      const ID = x + y
      _mine.checked(ID, spotArr, fn, num, spot)
    },
    checkRule8 (spot, spotArr, fn, num) {
      const x = spot.x + _mine.rule8.x + ''
      const y = spot.y + _mine.rule8.y + ''
      const ID = x + y
      _mine.checked(ID, spotArr, fn, num, spot)
    }
  },
  created () {},
  mounted () {
    _mine = this
    const myCanvas = document.getElementById('canvas')
    const backOne = document.getElementById('backOne')
    const beforeBackOne = document.getElementById('beforeBackOne')
    const ctx = myCanvas.getContext('2d')
    this.Ctx = ctx
    // 网格大小
    const grid = 40
    // 横竖方向要画多少线才是棋盘
    const lineTotal = Math.floor(ctx.canvas.width / grid)
    // 绘制棋盘
    this.drawCheckerBoard(ctx, grid, lineTotal)
    // 预绘制棋子
    this.drawPiece(ctx, grid, lineTotal)
    // 鼠标移入可放置棋子的区域显示为小手
    myCanvas.addEventListener('mousemove', function (e) {
      const coordinate = _mine.getMousePos(myCanvas, e)
      // 声明标志位 ifp = 1 则鼠标移入了可放置棋子的区域
      let ifp = 0
      for (let i = 0; i < _mine.piece.length; i++) {
        const p = _mine.piece[i].size
        if (p.min[0] < coordinate.x && p.max[0] > coordinate.x && p.min[1] < coordinate.y && p.max[1] > coordinate.y) {
          ifp = 1
        }
      }
      // 根据标志位显示鼠标样式
      if (ifp === 1) {
        _mine.$refs.body.style.cursor = 'pointer'
      } else {
        _mine.$refs.body.style.cursor = ''
      }
    })
    // 鼠标点击可放置棋子的区域放置棋子
    myCanvas.addEventListener('click', function (e) {
      if (_mine.isWinner) return false
      const color = ctx.getImageData(e.offsetX, e.offsetY, 1, 1)
      // 如果点击区域的rbg值的第一位是204或者255，说明该位置已被点击，不可再次点击
      if (color.data[0] === 204 || color.data[0] === 255) return false
      const coordinate = _mine.getMousePos(myCanvas, e)
      for (let i = 0; i < _mine.piece.length; i++) {
        const p = _mine.piece[i].size
        // 判断点击位置是否属于棋子位置
        if (p.min[0] < coordinate.x && p.max[0] > coordinate.x && p.min[1] < coordinate.y && p.max[1] > coordinate.y) {
          // 点的是棋子位置则重绘当前棋子
          ctx.beginPath()
          ctx.arc(_mine.piece[i].x, _mine.piece[i].y, 10, 0, Math.PI * 2)
          // 判断是绘制红棋还是灰棋
          // console.log(_mine.piece[i].sign)
          if (_mine.redOrblack) {
            // 灰棋
            _mine.redOrblack = false
            _mine.downSpot.push({ spot: _mine.piece[i], color: '#ccc' })
            _mine.redSpot.push(_mine.piece[i])
            ctx.fillStyle = '#ccc'
            ctx.fill()
            _mine.winner(_mine.piece[i], _mine.redSpot)
            return
          } else {
            // 红棋
            _mine.redOrblack = true
            _mine.downSpot.push({ spot: _mine.piece[i], color: 'red' })
            _mine.blackSpot.push(_mine.piece[i])
            ctx.fillStyle = 'red'
            ctx.fill()
            _mine.winner(_mine.piece[i], _mine.blackSpot)
            return
          }
        }
      }
    })
    // 悔棋操作
    backOne.addEventListener('click', function (e) {
      if (_mine.isWinner) return false
      // 如果已放置的棋子数组为空，则不向下执行
      if (_mine.downSpot.length === 0) return false
      const spotID = _mine.downSpot.pop()
      // 防止重绘的网格超出边界
      let x1 = spotID.spot.x - 10
      x1 = x1 < 20 ? 20 : x1
      let x2 = spotID.spot.x + 10
      x2 = x2 > 580 ? 580 : x2
      let y1 = spotID.spot.y - 10
      y1 = y1 < 20 ? 20 : y1
      let y2 = spotID.spot.y + 10
      y2 = y2 < 580 ? 580 : y2
      ctx.beginPath()
      ctx.clearRect(spotID.spot.x - 10, spotID.spot.y - 10, 20, 20)
      ctx.moveTo(x1, spotID.spot.y)
      ctx.lineTo(x2, spotID.spot.y)
      ctx.moveTo(spotID.spot.x, y1)
      ctx.lineTo(spotID.spot.x, y2)
      ctx.stroke()
      _mine.regret.push(spotID)
      _mine.redOrblack = !_mine.redOrblack
      // 把悔的棋从对应颜色的数组中删掉
      if (_mine.redOrblack) {
        _mine.redSpot.pop(spotID)
      } else {
        _mine.blackSpot.pop(spotID)
      }
    })
    // 撤销悔棋
    beforeBackOne.addEventListener('click', function (e) {
      if (_mine.isWinner) return false
      // 如果悔棋数组为空则不向下执行
      if (_mine.regret.length === 0) return false
      const spotID = _mine.regret.pop()
      ctx.beginPath()
      ctx.arc(spotID.spot.x, spotID.spot.y, 10, 0, Math.PI * 2)
      ctx.fillStyle = spotID.color
      ctx.fill()
      _mine.downSpot.push(spotID)
      _mine.redOrblack = !_mine.redOrblack
      // 把撤销的棋子塞回对应的数组
      if (_mine.redOrblack) {
        _mine.redSpot.pop(spotID)
      } else {
        _mine.blackSpot.pop(spotID)
      }
    })
  }
}
</script>
<style lang='less' scoped>
.box{
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}
</style>
